﻿using System;
using System.Collections;
using System.Linq;
using System.Text;

namespace ThreadSafeControls {
    internal sealed class SynchronizedObjectCollection : IList {

        private readonly IList _list;

        public SynchronizedObjectCollection(IList list) {
            if (list == null)
                throw new ArgumentNullException("list");

            _list = list;
        }

        public object this[int index] {
            get {
                return ReturnAsync(() => _list[index]);
            }
            set {
                UpdateAsync(() => _list[index] = value);
            }
        }

        public int Count {
            get { return ReturnAsync(() => _list.Count); }
        }

        public bool IsSynchronized {
            get { return true; }
        }

        public object SyncRoot {
            get { return _list.SyncRoot; }
        }

        public bool IsFixedSize {
            get { return _list.IsFixedSize; }
        }

        public bool IsReadOnly {
            get { return _list.IsReadOnly; }
        }

        public int Add(object value) {
            return ReturnAsync(() => _list.Add(value));
        }

        public void Clear() {
            UpdateAsync(() => _list.Clear());
        }

        public bool Contains(object value) {
            return ReturnAsync(() => _list.Contains(value));
        }

        public int IndexOf(object value) {
            return ReturnAsync(() => _list.IndexOf(value));
        }

        public void Insert(int index, object value) {
            UpdateAsync(() => _list.Insert(index, value));
        }


        public void Remove(object value) {
            UpdateAsync(() => _list.Remove(value));
        }

        public void RemoveAt(int index) {
            UpdateAsync(() => _list.RemoveAt(index));
        }

        public void CopyTo(Array array, int index) {
            UpdateAsync(() => _list.CopyTo(array, index));
        }

        public IEnumerator GetEnumerator() {
            return ReturnAsync(() => _list.GetEnumerator());
        }

        private void UpdateAsync(Action action) {
            lock (_list.SyncRoot)
                action();
        }

        private TResult ReturnAsync<TResult>(Func<TResult> func) {
            lock (_list.SyncRoot)
                return func();
        }

    }
}
